home *** CD-ROM | disk | FTP | other *** search
/ Best of Shareware / Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso / mac / ZIPPED / DOS / GRAPHICS / R386DEV4.ZIP / DEMO4.C < prev    next >
C/C++ Source or Header  |  1992-09-29  |  21KB  |  861 lines

  1. /* A simple user-interface demo -- Version 4 */
  2.  
  3. /* Written by Bernie Roehl, February 1992 */
  4.  
  5. /* Latest version (re)written June 1992 */
  6.  
  7. /* Contact: broehl@sunee.waterloo.edu */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <ctype.h>   /* toupper() */
  13. #include <string.h>
  14. #include <mem.h>     /* memmove() */
  15. #include <dos.h>
  16.  
  17. #include "include/rend386.h"
  18. #include "include/intmath.h"
  19. #include "include/plg.h"
  20. #include "include/segio.h"
  21. #include "include/segasupp.h"
  22. #include "include/splits.h"
  23. #include "include/pointer.h"
  24. #include "include/tasks.h"
  25. #include "include/cursor.h"
  26. #include "include/userint.h"
  27.  
  28. extern void *screen_data();
  29.  
  30. extern unsigned _stklen = 10000;
  31.  
  32. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  33.  
  34. /* default screen data setup */
  35.  
  36. STEREO default_stereo = {
  37.     600 , 240, 320, 50, 600, 1*65536L };
  38.  
  39. VIEW default_view = {
  40.     0,0,-8000, /* ex,ey,ez */
  41.     0,0,0, /* pan,tilt,roll */
  42.     4*65536L, /* zoom */
  43.     1000,15000,-5000, /* lx,ly,lz */
  44.     0,63, /* point, ambient */
  45.     0,319,0,200, /* left,right,top,bottom */
  46.     1,100000, /* hither, yon */
  47.     1/1.25*65536L, /* aspect ratio */
  48.     0, /* flags */
  49.     0,0, /* no offset */
  50.     0 /* no flip */
  51. }; /* don't init. matrix */
  52.  
  53. VIEW *current_view = &default_view;
  54.  
  55. VIEW orig_view; /* used for '*' key */
  56.  
  57. int v_page = 0; /* screen page swap variable */
  58.  
  59. OBJLIST *objlist; /* the linked list of objects in the scene */
  60.  
  61. int running = 1; /* non-zero until we're ready to exit */
  62. int redraw = 1; /* non-zero if we need a redraw */
  63. int review = 1; /* non-zero if we need to recompute current view */
  64. int reframe = 1; /* non-zero if we need to copy our frame back on-screen */
  65.  
  66. int do_horizon = 1;
  67.  
  68. int stereo_type = MONOSCOPIC;
  69.  
  70. extern int use_old_keys; /* NEED TO SET DISTANCE AS WELL ! */
  71.  
  72. int have_joystick = 0; /* non-zero if we have one or more joysticks */
  73. joystick_data joy;
  74.  
  75. long spacestep = 10L; /* "granularity" of motion */
  76.  
  77. unsigned lastkey = 0, nextolastkey = 0;
  78.  
  79. char *progname = "demo";
  80.  
  81. char vdname[40] = "vd256.rvd";
  82. int vdmode = 0x14;
  83.  
  84. char swdname[40] = "sega";
  85.  
  86. char mdname[40] = "mouse";
  87. PDRIVER *cursor_device = NULL; /* primary mouse device   */
  88. PDRIVER *menu_device = NULL; /* secondary mouse device */
  89. int manip_2D_avail = 0; /* can do mouse manipulation */
  90.  
  91. char gpdname[40] = "pglove";
  92. char gpcursor[40] = "handsm.fig";
  93. float gpdo_x = 1, gpdo_y = 1, gpdo_z = 2, gpdo_rx = 1, gpdo_ry = 1, gpdo_rz = 1;
  94. int have_glove = 0;
  95. int have_ptr = 0;
  96. PDRIVER *manip_device = NULL; /* extended manip. device (glove or pointer) */
  97.  
  98. char hdname[40] = "none";
  99. float hdo_x = 0, hdo_y = 0, hdo_z = 0; /* relative pos'n to neck */
  100. float hdo_rx = 0, hdo_ry = 0, hdo_rz = 0;
  101. PDRIVER *head_device = NULL; /* head tracking device   */
  102.  
  103.  
  104. MATRIX head_tracker_map = { 
  105.     XFSC, 0, 0, 0, XFSC, 0, 0, 0, XFSC, 0, 0, 0 };
  106.  
  107. int sl_xflip = 0, sl_xoff = 0;
  108. long sl_left = -1, sl_top, sl_right, sl_bottom;
  109. int sr_xflip = 0, sr_xoff = 0;
  110. long sr_left = -1, sr_top, sr_right, sr_bottom;
  111. float sl_xrot = 0, sr_xrot = 0;
  112.  
  113. int use_glove = 0;
  114. int use_ht = 0;
  115. int use_wide = 0;
  116. int use_BW = 0;
  117. int swap_eyes = 0;
  118. int vd_loaded = 0;
  119.  
  120. int fancy_background = 0; /* if set, we display a fancy background */
  121. int reflection_pool = 0; /* if set, draw a "reflecting pool" at the bottom of the screen */
  122. int have_logo = 0; /* if set, we have a logo */
  123. int show_logo = 0; /* if set, show the logo (if we have one) */
  124. int show_location = 1; /* if set, we display the current location on-screen */
  125. int show_compass = 1; /* if set, we display the 3-D compass on-screen */
  126. int show_framerate = 1; /* if set, we display the frames/second rate */
  127. int do_screen_clear = 1; /* by default, we clear the screen on each frame */
  128. int use_frame = 0; /* if set, draw a "frame" */
  129. int frame_x = 0, frame_y = 0, frame_w = 320, frame_h = 200; /* frame location */
  130.  
  131. TASK *tasklist = NULL;
  132.  
  133. SPLIT *split_tree = NULL;
  134.  
  135. int npalette = 0; /* non-zero if we have a palette loaded */
  136. unsigned char palette[256*3];
  137.  
  138. extern unsigned getkey();
  139.  
  140. char framefname[100];
  141.  
  142. extern struct Screeninfo *screeninfo;
  143. extern highest_color;
  144.  
  145. char loadpath[100] = "";
  146.  
  147. static char tempname[100];
  148.  
  149. char *fix_fname(char *name)
  150. {
  151.     if (loadpath[0] && !strchr(name, '\\') && !strchr(name, '/'))
  152.         sprintf(tempname, "%s\\%s", loadpath, name);
  153.     else
  154.         strcpy(tempname, name);
  155.     return tempname;
  156. }
  157.  
  158. void *v_driver_pointer = NULL;
  159.  
  160. void load_video_driver(char *dfile)
  161. {
  162.     v_driver_pointer = load_driver(dfile);
  163.     if (v_driver_pointer == NULL)
  164.     {
  165.         fprintf(stderr,"Cannot read video driver %s\n", dfile);
  166.         exit(0);
  167.     }
  168. }
  169.  
  170. void main(int argc, char *argv[])
  171. {
  172.     OBJECT *obj;
  173.     void wrap(); /* wrap-up function, shuts everything down */
  174.     void joystick_calibration(), refresh_display();
  175.     unsigned getkey();
  176.     long x, y, z;
  177.     FILE *in;
  178.     int i;
  179.     PDRIVER *dm;
  180.     POINTER *p;
  181.     char *fname;
  182.  
  183.     if ((progname = strrchr(argv[0], '.')) != NULL) *progname = '\0';
  184.     progname = argv[0];
  185.  
  186.     if (getenv("REND386"))
  187.         strcpy(loadpath, getenv("REND386"));
  188.  
  189.     setup_render(40,800); /* # of K, # of polys */
  190.     atexit(wrap);
  191.     set_global_split_root(&split_tree);
  192.     initial_world_split(&split_tree);
  193.     set_move_handler(split_move_handler);
  194.     objlist = new_objlist();
  195.  
  196.     i = 1;
  197.     if(!stricmp(&(argv[1][0]), "/C"))
  198.     {
  199.         i = 2;
  200.         fname = &(argv[2][0]);
  201.     }
  202.     else fname = "rend386.cfg";
  203.  
  204.     if ((in = fopen(fname, "r")) == NULL)
  205.         fprintf(stderr, "Note -- config file '%s' not found; using defaults.\n", fname);
  206.     else
  207.         {
  208.         if (read_world(in))
  209.             fprintf(stderr, "Error reading config file '%s'\n", fname);
  210.         fclose(in);
  211.     }
  212.  
  213.     for (; i < argc; ++i)
  214.     {
  215.         if (argv[i][0] == '/' || argv[i][0] == '-')
  216.         {
  217.             switch(toupper(argv[i][1]))
  218.             {
  219.             case 'M':/* mirror stereo */
  220.                 stereo_type = SPLITLR;
  221.                 /* possibly problem here: assumes 320x200 mode before checking */
  222.                 default_stereo.phys_screen_dist = 200;
  223.                 default_stereo.phys_convergence = 700;
  224.                 default_stereo.phys_screen_width = 120;
  225.                 default_stereo.pixel_width = 160;
  226.                 default_view.right = 159;
  227.                 compute_stereo_data(&default_stereo, 0, 0, 0, 0, 0, 0, 159, 100);
  228.                 compute_stereo_data(&default_stereo, 1, 1, 0, 0, 160, 0, 319, 100);
  229.                 break;
  230.             case 'R':/* swap eyes on Sega driver */
  231.                 swap_eyes = 1;
  232.                 break;
  233.             case 'C':/* set conv. distance */
  234.                 default_stereo.phys_screen_dist = atol(argv[++i]);
  235.                 break;
  236.             case 'S':/* set world scale */
  237.                 default_stereo.world_scaling = 65536.0*atof(argv[++i]);
  238.                 break;
  239.             case 'E':/* set eye spacing */
  240.                 default_stereo.phys_eye_spacing = atol(argv[++i]);
  241.                 break;
  242.             case 'X':/* turn on stereo */
  243.                 stereo_type = SWITCHED;
  244.                 break;
  245.             case 'J':/* sort by object (default is polys) */
  246.                 set_default_depth_sort(get_default_depth_sort() | BYOBJECT);
  247.                 break;
  248.             case 'P':/* depth sort-- deepest */
  249.                 set_default_depth_sort(get_default_depth_sort() & (~(BYOBJECT|AVERAGE|ATBACK)));
  250.                 break;
  251.             case 'A':/* depth sort-- middle */
  252.                 set_default_depth_sort(get_default_depth_sort() | AVERAGE);
  253.                 break;
  254.             case '1':/* com 1 for SEGA */
  255.                 select_sega_port(0x3FC);
  256.                 break;
  257.             case '2':/* com 2 for SEGA */
  258.                 select_sega_port(0x2FC);
  259.                 break;
  260.             case 'G':/* enable glove */
  261.                 use_glove = 1;
  262.                 if(!have_ptr) have_glove = 1;
  263.                 break;
  264.             case 'H':/* enable head tracker */
  265.                 use_ht = 1;
  266.                 break;
  267.             case 'W':/* enable wide-angle dual-VGA displays */
  268.                 use_wide = 1;
  269.                 stereo_type = SEPARATE;
  270.                 default_stereo.phys_screen_dist = 50;
  271.                 default_stereo.phys_convergence = 1200;
  272.                 default_stereo.phys_screen_width = 115;
  273.                 default_stereo.pixel_width = 320; /* hmm... may vary */
  274.                 break;
  275.             case 'B':/* force all colors to monochrome */
  276.                 use_BW = 1;
  277.                 break;
  278.             }
  279.         }
  280.         else
  281.             {
  282.             char *in_filename;
  283.             in_filename = fix_fname(argv[i]);
  284.             if ((in = fopen(in_filename, "r")) == NULL)
  285.                 fprintf(stderr, "Could not open '%s'\n", in_filename);
  286.             else
  287.                 if (strstr(in_filename,".plg")) /* check if plg or fig file */
  288.             {
  289.                 set_loadplg_offset(0,0,0);
  290.                 set_loadplg_scale(1,1,1);
  291.                 while ((obj = load_plg(in)) != NULL)
  292.                 {
  293.                     SEGMENT *s;
  294.                     add_to_objlist(objlist, obj);
  295.                     if ((s = new_seg(NULL)) == NULL)
  296.                         fprintf(stderr, "Warning: out of memory while loading an object\n");
  297.                     else
  298.                         {
  299.                         seg_set_object(s, obj);
  300.                         set_object_owner(obj, s);
  301.                         update_segment(s);
  302.                     }
  303.                     if (spacestep < get_object_bounds(obj, &x, &y, &z)/5L)
  304.                         spacestep = get_object_bounds(obj, &x, &y, &z)/5L;
  305.                 }
  306.                 if (load_err)
  307.                 {
  308.                     fprintf(stderr, "Load error: %d\n", load_err);
  309.                     getkey();
  310.                 }
  311.             }
  312.             else if (strstr(in_filename,".fig")) /* check if plg or fig file */
  313.             {
  314.                 SEGMENT *s;
  315.                 int c;
  316.                 set_readseg_objlist(objlist);
  317.                 if ((s = readseg(in, NULL)) == NULL)
  318.                     fprintf(stderr, "Could not read '%s'\n", argv[i]);
  319.                 else
  320.                     update_segment(s);
  321.             }
  322.             else {
  323.                 if (read_world(in))
  324.                     fprintf(stderr, "Error reading world file\n");
  325.             }
  326.             fclose(in);
  327.         }
  328.     }
  329.  
  330.     have_joystick = joystick_check();
  331.  
  332.     load_video_driver(vdname);
  333.     screeninfo = screen_data();
  334.     highest_color = screeninfo->colors-1;
  335.     preset_default_colors();
  336.  
  337.     frame_x = screeninfo->xmin;
  338.     frame_y = screeninfo->ymin;
  339.     frame_w = screeninfo->xmax - screeninfo->xmin + 1;
  340.     frame_h = screeninfo->ymax - screeninfo->ymin + 1;
  341.  
  342.     /* Default view is full-screen: */
  343.     default_view.left = screeninfo->xmin;
  344.     default_view.top = screeninfo->ymin;
  345.     default_view.right = screeninfo->xmax;
  346.     default_view.bottom = screeninfo->ymax;
  347.     default_view.aspect = screeninfo->aspect;
  348.  
  349.     orig_view = default_view;
  350.  
  351.     if (enter_graphics())
  352.     {
  353.         fprintf(stderr, "Could not enter graphics mode\n");
  354.         exit(1);
  355.     }
  356.     vd_loaded++;
  357.  
  358.     initialize_screen_factors(current_view);
  359.     fast_view_factors(current_view);
  360.  
  361.     if (npalette)
  362.         load_DAC_colors(palette, highest_color+1, use_BW);
  363.  
  364.     if (use_frame)
  365.     {
  366.         FILE *in;
  367.         use_frame = 0; /* we only set it back to 1 if we're successful */
  368.         if(stereo_type == MONOSCOPIC)
  369.             if ((in = fopen(fix_fname(framefname), "rb")) != NULL)
  370.             {
  371.                 if (load_pcx(in, 3) == 0) use_frame = 1;
  372.                 copy_block(3, 0, 0, 0, frame_x, frame_y, frame_w, frame_h);
  373.                 copy_block(3, 0, 0, 1, frame_x, frame_y, frame_w, frame_h);
  374.                 copy_block(3, 0, 0, 2, frame_x, frame_y, frame_w, frame_h);
  375.                 fclose(in);
  376.             }
  377.     }
  378.  
  379.     init_body_links();
  380.  
  381.     if(stereo_type != MONOSCOPIC)
  382.     {
  383.         init_switch_driver(swdname);
  384.  
  385.         if(sl_left<0)
  386.         {
  387.             sl_left = default_view.left;
  388.             sl_right = default_view.right;
  389.             sl_top = default_view.top;
  390.             sl_bottom = default_view.bottom;
  391.         }
  392.         compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  393.         sl_left, sl_top, sl_right, sl_bottom);
  394.  
  395.         if(sr_left<0)
  396.         {
  397.             sr_left = default_view.left;
  398.             sr_right = default_view.right;
  399.             sr_top = default_view.top;
  400.             sr_bottom = default_view.bottom;
  401.         }
  402.         compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  403.         sr_left, sr_top, sr_right, sr_bottom);
  404.     }
  405.  
  406.     if ((dm=mouseptr_init(mdname))!=NULL)
  407.     {
  408.         cursor_show(v_page);
  409.         manip_2D_avail++;
  410.     }
  411.     cursor_device = dm;
  412.     menu_device = dm;
  413.  
  414.     if(stricmp(hdname,"none") && use_ht)
  415.     {
  416.         extern PDRIVER *init_head_device(char *name, long x, long y, long z, long rx, long ry, long rz);
  417.         head_device = init_head_device(hdname, hdo_x, hdo_y, hdo_z,
  418.         hdo_rx*65536.0, hdo_ry*65536.0, hdo_rz*65536.0);
  419.     }
  420.  
  421.     if ((!use_glove) || have_ptr || stricmp(gpdname,"pglove")) /* not going to be using powerglove */
  422.     {
  423.         if(stereo_type==SWITCHED)
  424.             init_SG_interrupt(switch_sega,NULL,6500);
  425.         else init_timer();
  426.     }
  427.  
  428.     if(use_glove && (!have_ptr))
  429.     {
  430.         extern SEGMENT *body_seg;
  431.         PDRIVER *gd;
  432.         extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  433.  
  434.         gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  435.         gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  436.         manip_device = menu_device = gd;
  437.         if(gd)
  438.             load_glove_cursor(body_seg, manip_device, gpcursor);
  439.         else have_glove = use_glove = 0;
  440.     }
  441.  
  442.     if(use_glove && have_ptr)
  443.     {
  444.         extern SEGMENT *body_seg;
  445.         PDRIVER *gd;
  446.         extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  447.  
  448.         gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  449.         gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  450.         manip_device = menu_device = gd;
  451.         if(gd)
  452.         {
  453.             set_loadplg_offset(0, 0, 0);
  454.             set_loadplg_scale(1, 1, 1);
  455.             load_3D_cursor(body_seg, manip_device, gpcursor);
  456.         }
  457.         else have_ptr = use_glove = 0;
  458.     }
  459.  
  460.     if ((have_joystick) != 0)
  461.     {
  462. #ifdef ASKUSER
  463.         popmsg("Joystick found -- use it?");
  464.         reframe = 1;
  465.         joystick_read(&joy);
  466.         while(!kbhit() && (joy.buttons==0)) joystick_read(&joy);
  467.         if(joy.buttons || toupper(getkey()) == 'Y')
  468.         {
  469.             refresh_display();
  470.             joystick_calibration(&joy);
  471.         }
  472.         else
  473.             have_joystick = 0;
  474.         refresh_display();
  475. #else
  476.         joystick_calibration(&joy);
  477. #endif
  478.     }
  479.  
  480.     while (running)
  481.     {
  482.         int x, y;
  483.         unsigned buttons;
  484.  
  485.         if (cursor_device) move_and_select_2D(cursor_device);
  486.  
  487.         if (have_joystick)
  488.             if (joystick_read(&joy))
  489.                 do_joy(&joy);
  490.         if (bioskey(1))
  491.         {
  492.             do_key(nextolastkey = getkey());
  493.             lastkey = nextolastkey;
  494.         }
  495.  
  496.         if(head_device && use_ht) head_update(0);
  497.  
  498.         if (use_glove)
  499.         {
  500.             POINTER gp;
  501.             int g;
  502.  
  503.             if(!have_ptr)
  504.             {
  505.                 glove_update(manip_device, &gp);
  506.                 switch(gp.gesture)
  507.                 {
  508.                 case G_FIST :
  509.                     g = GRASP_DO; 
  510.                     break;
  511.                 case G_PINCH:
  512.                     g = ROTATE_DO; 
  513.                     break;
  514.                 case G_POINT:
  515.                     g = SELECT_DO; 
  516.                     break;
  517.                 default:
  518.                     g = FREE_DO; 
  519.                     break;
  520.                 }
  521.             }
  522.             else
  523.                 {
  524.                 cursor_update3D(manip_device, &gp);
  525.                 switch(gp.buttons)
  526.                 {
  527.                 case 2:
  528.                     g = GRASP_DO; 
  529.                     break;
  530.                 case 3:
  531.                     g = ROTATE_DO; 
  532.                     break;
  533.                 case 1:
  534.                     g = SELECT_DO; 
  535.                     break;
  536.                 default:
  537.                     g = FREE_DO; 
  538.                     break;
  539.                 }
  540.             }
  541.  
  542.             manip_do(manip_device,g);
  543.         }
  544.  
  545.         run_tasks(tasklist);
  546.  
  547.         if (redraw) refresh_display();
  548.     }
  549. }
  550.  
  551.  
  552. static char *closing_msg[] = {
  553.     "",
  554.     "The libraries used in this package are available on the Internet,",
  555.     "via anonymous ftp to sunee.uwaterloo.ca in pub/rend386.",
  556.     "",
  557.     "For more information, send e-mail to:",
  558.     "    Bernie Roehl  (broehl@sunee.uwaterloo.ca)",
  559.     "    Dave Stampe   (dstampe@sunee.uwaterloo.ca)",
  560.     "",
  561.     NULL};
  562.  
  563.  
  564. void wrap() /* end program */
  565. {
  566.     int i;
  567.  
  568.     if (have_joystick) joystick_quit();
  569.     if(vd_loaded) exit_graphics();
  570.     reset_render();
  571.     for (i = 0; closing_msg[i]; ++i)
  572.         fprintf(stderr, "%s\n", closing_msg[i]);
  573.     exit(0);
  574. }
  575.  
  576.  
  577.  
  578. static l_x = 1000, l_y = 15000, l_z = -5000; /* light source */
  579.  
  580. long center_d = 10000;
  581. long center_x = 0;
  582. long center_y = 0;
  583. long center_z = 0;
  584. long latitude = 0;
  585. long longitude = 0;
  586. long center_roll = 0;
  587.  
  588. static long light_d = 1000000;
  589.  
  590. void polar_compute()
  591. {
  592.     MATRIX m,n;
  593.  
  594.     long x = 0;
  595.     long y = 0;
  596.     long z = -center_d;
  597.  
  598.     std_matrix(n,longitude,latitude,center_roll,0,0,0);
  599.  
  600.     matrix_point(n,&x,&y,&z);
  601.     current_view->ex = x + center_x;
  602.     current_view->ey = y + center_y;
  603.     current_view->ez = z + center_z;
  604.  
  605.     x = l_x;
  606.     y = l_y; 
  607.     z = l_z;
  608.     matrix_point(n,&x,&y,&z);
  609.     current_view->lx = x;
  610.     current_view->ly = y;
  611.     current_view->lz = z;
  612.     current_view->pan = latitude;
  613.     current_view->tilt = longitude;
  614.     current_view->roll = center_roll;
  615. }
  616.  
  617.  
  618. void refresh_display()
  619. {
  620.     VIEW v;
  621.  
  622.     if (use_old_keys) polar_compute();
  623.     initialize_screen_factors(current_view);
  624.  
  625.     if(!(use_glove || head_device))
  626.     {
  627.         fast_view_factors(current_view);
  628.         screen_refresh(current_view);
  629.     }
  630.     else
  631.         {
  632.         body_centric_map(current_view, &v);
  633.         screen_refresh(&v);
  634.     }
  635.  
  636.     redraw = 0;
  637. }
  638.  
  639.  
  640.  
  641. load_logo(char *filename)
  642. {
  643.     char far *buffer;
  644.     FILE *in;
  645.     if ((in = fopen(fix_fname(filename), "rb")) == NULL) return 0;
  646.     if (load_pcx(in, 3)) { /* some sort of problem loading it in */
  647.         fclose(in);
  648.         return 0;
  649.     }
  650.     fclose(in);
  651.     return 1; /* all is well... we have a logo */
  652. }
  653.  
  654. resize_viewport()
  655. {
  656.     int top, left, bottom, right;
  657.     unsigned buttons;
  658.     cursor_hide();
  659.     clear_display(v_page);
  660.     cursor_show(v_page);
  661.     popmsg("Click top-left and drag");
  662.     do {
  663.         move_2D(cursor_device, &left, &top, &buttons);
  664.     }
  665.     while (buttons == 0);
  666.     while (buttons) {
  667.         while (!move_2D(cursor_device, &right, &bottom, &buttons));
  668.         clear_display(v_page);
  669.         vgabox(left, top, right, bottom, 15);
  670.     }
  671.     if (right - left > 10) {
  672.         current_view->left = left & (~0x0007); /* always on a 16-pixel boundary */
  673.         current_view->right = (right & (~0x0007)) + 7;
  674.     }
  675.     if (bottom - top > 10) {
  676.         current_view->top = top;
  677.         current_view->bottom = bottom;
  678.     }
  679.  
  680.  if(stereo_type == SWITCHED)  /* makes sense for Sega only (no shift) */
  681.     {
  682.         compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  683.         current_view->left, current_view->top, current_view->right, current_view->bottom);
  684.         compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  685.         current_view->left, current_view->top, current_view->right, current_view->bottom);
  686.     }
  687.  
  688.     /* Make sure all pages are refreshed: */
  689.     reset_screens();
  690.     refresh_display();
  691.     return 0;
  692. }
  693.  
  694. save_pcx_file()
  695. {
  696.     char filename[100];
  697.     char far *buffer;
  698.     FILE *out;
  699.     refresh_display();
  700.     askfor("File to save to? ", filename, 15);
  701.     reframe = 1;
  702.     if (filename[0] == '\0') return 1;
  703.     refresh_display();
  704.     if ((out = fopen(filename, "wb")) == NULL) {
  705.         popmsg("Could not open file");
  706.         reframe = 1;
  707.         getkey();
  708.         return 3;
  709.     }
  710.     cursor_hide();
  711.     save_pcx(out, v_page);
  712.     cursor_show(v_page);
  713.     fclose(out);
  714.     return 0;
  715. }
  716.  
  717. /* Some support routines */
  718.  
  719. static void center(char *s, int w)
  720. {
  721.     int n;
  722.  
  723.     if (strlen(s) == 0) return;
  724.     n = (w - strlen(s)) /2;
  725.     memmove(&s[n], s, strlen(s)+1);
  726.     memset(s, ' ', n);
  727. }
  728.  
  729. disp_status(VIEW *v)
  730. {
  731.     char *text[9], a[80], b[80], c[80], d[80], e[80], f[80], g[80];
  732.     int w, i;
  733.  
  734.     text[0] = a; 
  735.     text[1] = "";
  736.     text[2] = b; 
  737.     text[3] = c; 
  738.     text[4] = d; 
  739.     text[5] = e; 
  740.     text[6] = f;
  741.     text[7] = g; 
  742.     text[8] = NULL;
  743.     sprintf(a, "STATUS");
  744.  
  745.     sprintf(b, "X = %ld  Y = %ld  Z = %ld", v->ex, v->ey, v->ez);
  746.     w = strlen(b);
  747.     sprintf(c, "Pan = %ld   Tilt = %ld   Roll = %ld  ", v->pan/65536L, v->tilt/65536L, v->roll/65536L);
  748.     if (strlen(c) > w) w = strlen(c);
  749.     sprintf(d, "Zoom = %ld", v->zoom/65536L);
  750.     if (strlen(d) > w) w = strlen(d);
  751.     sprintf(e, "Hither = %ld  Yon = %ld", v->hither, v->yon);
  752.     if (strlen(e) > w) w = strlen(e);
  753.  
  754.     if (have_joystick)
  755.     {
  756.         joystick_read(&joy);
  757.         sprintf(f, "Joystick = %d,%d", joy.x, joy.y);
  758.         if (strlen(f) > w) w = strlen(f);
  759.     }
  760.     else
  761.         text[6] = NULL;
  762.     text[7] = NULL;
  763.  
  764.     for (i = 0; text[i]; ++i) center(text[i], w);
  765.     poptext(text);
  766.     reframe = 1;
  767.     getkey();
  768.     return 0;
  769. }
  770.  
  771.  
  772. void joystick_calibration(joystick_data *joy)
  773. {
  774.     if (have_joystick == 0) return;
  775.     if (have_joystick & 1) joystick_init(joy, 0);
  776.     else if (have_joystick & 2) joystick_init(joy, 1);
  777.  
  778.     joystick_setscale(joy, 100);
  779.     reframe = 1;
  780. }
  781.  
  782. static int nobjs, nverts, npolys;
  783.  
  784. void gather_data(OBJECT *obj)
  785. {
  786.     int nv = 0, np = 0;
  787.     get_obj_info(obj, &nv, &np);
  788.     ++nobjs;
  789.     nverts += nv;
  790.     npolys += np;
  791. }
  792.  
  793. disp_info()
  794. {
  795.     OBJECT *obj;
  796.     char buff[100];
  797.     nobjs = 0, nverts = 0, npolys = 0;
  798.  
  799.     walk_split_tree(split_tree, gather_data);
  800.     sprintf(buff, "%d object%s, %d vertice%s, %d polygon%s", nobjs,
  801.     (nobjs == 1) ? "" : "s", nverts, (nverts == 1) ? "" : "s",
  802.     npolys, (npolys == 1) ? "" : "s");
  803.     popmsg(buff);
  804.     reframe = 1;
  805.     getkey();
  806.     return 0;
  807. }
  808.  
  809. extern AREA *areas;
  810.  
  811. extern POINTER gloveptr;
  812.  
  813. char *gest[] = {
  814.     "FLAT", "THUMB_IN", "INDEX_IN", "MIDDLE_IN",
  815.     "RING_IN", "PINCH", "FIST", "THUMB_OUT", "POINT",
  816.     "BADFINGER", "RING_OUT", "??????" };
  817.  
  818. void prprint(int x,int y, int color, char *t)
  819. {
  820.     int bk = (color>8) ? 0 : 15;
  821.  
  822.     printxyr(x,y,bk,t,0);
  823.     printxyr(x+1,y+1,color,t,0);
  824. }
  825.  
  826. status_on_screen()
  827. {
  828.     char buff[100];
  829.     AREA *a, *what_area();
  830.     long floor_at(), ceiling_at();
  831.     extern void *find_value();
  832.  
  833.     if (show_location == 0) return 0;
  834.  
  835.     sprintf(buff, "Pos(x,z): %ld,%ld", current_view->ex, current_view->ez);
  836.     prprint(2,3,15,buff);
  837.     sprintf(buff, "Not in any area");
  838.     a = what_area(split_tree, current_view->ex, current_view->ey, current_view->ez);
  839.     if (a)
  840.     {
  841.         char *p = find_value(areas, a);
  842.         if (p)
  843.             sprintf(buff, "Area: %s", p);
  844.     }
  845.     prprint(2,15,15,buff);
  846.  
  847.     if (use_glove)
  848.     {
  849.         int sl;
  850.         POINTER p;
  851.  
  852.         last_pointer(manip_device, &p);
  853.         sprintf(buff,"Glove: %s",gest[p.gesture]);
  854.         sl = strlen(buff)<<3;
  855.         prprint(300-sl,3,15,buff);
  856.     }
  857.     return 0;
  858.  
  859. }
  860.  
  861.